package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotDelException;
import com.mysema.query.BooleanBuilder;

import java.util.List;

@Service
@Transactional
public class ProductService {

	@Autowired
	private ProductDao productDao;

	private QProduct $ = QProduct.product;

	@Autowired
	private ProjectDeliveryDao projectDeliveryDao;

	private QProjectDelivery $_1 = QProjectDelivery.projectDelivery;

	@Autowired
	private ProjectProductDao projectProductDao;
	
	private QProjectProduct $_2 = QProjectProduct.projectProduct;
	
	@Autowired
	public void setProjectProductDao(ProjectProductDao projectProductDao) {
		this.projectProductDao = projectProductDao;
	}

	@Autowired
	public void setProjectDeliveryDao(ProjectDeliveryDao projectDeliveryDao) {
		this.projectDeliveryDao = projectDeliveryDao;
	}

	@Autowired
	public void setProductDao(ProductDao productDao) {
		this.productDao = productDao;
	}

	public List<Product> findAll() {
		return ListUtil.toList(productDao.findAll());
	}
	
	public Product findOne(Long id){
		return this.productDao.findOne(id);
	}

	public List<Product> findAll(String productCode, String name, String spec,
			Long productCategoryId, String remark, String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (StringUtil.isNotEmpty(productCode)) {
			condition.and($.productCode.contains(productCode));
		}

		if (StringUtil.isNotEmpty(name)) {
			condition.and($.name.contains(name));
		}

		if (StringUtil.isNotEmpty(spec)) {
			condition.and($.spec.contains(spec));
		}

		if (IdUtil.isNotEmpty(productCategoryId)) {
			condition.and($.productCategory.id.eq(productCategoryId));
		}

		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}

		return ListUtil.toList(productDao.findAll(condition));
	}

	public Page<Product> findAll(String productCode, String name, String spec,
			Long productCategoryId, String remark, int pageNumber,
			int pageSize, String sortAttribute, String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if (StringUtil.isNotEmpty(productCode)) {
			condition.and($.productCode.contains(productCode));
		}
		if (StringUtil.isNotEmpty(name)) {
			condition.and($.name.contains(name));
		}
		if (StringUtil.isNotEmpty(spec)) {
			condition.and($.spec.contains(spec));
		}
		if (IdUtil.isNotEmpty(productCategoryId)) {
			condition.and($.productCategory.id.eq(productCategoryId));
		}
		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.DESC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),
					sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize,
				sortObject);
		return productDao.findAll(condition, pageRequest);
	}

	public Product getProduct(Long id) {
		return productDao.getOne(id);
	}

	public void deleteProduct(Long id) throws CannotDelException {
		if (this.findProjectDeliveryByProject(id)) {
			throw new CannotDelException("产品已被项目交付物引用，无法删除！");
		} if(this.findProjectProjectByProject(id)) {
			throw new CannotDelException("产品已被项目产品引用，无法删除！");
		} else {
			productDao.delete(id);
		}
	}
	
	private boolean findProjectDeliveryByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_1.product.id.eq(projectId));
		return this.projectDeliveryDao.count(condition) > 0;
	}
	
	private boolean findProjectProjectByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_2.product.id.eq(projectId));
		return this.projectProductDao.count(condition) > 0;
	}

	public void saveProduct(Product product) {
		productDao.save(product);
	}

}
